import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class ValueFilter {

	// 在连续的N次数据中，放行Y次相同的内容
	// 在连续100个数据中，放行5个相同的内容
	// 加入新的数据后，要移除最旧的数据
	// 10 10 10 10 10 10 10 10 10 10（原始数据）
	// 10（加入的新数据）
	// 分析出，要保留数据的存储顺序，才能做到加入新数据，移除旧数据
	// 存储数据和移除数据时，更新每样数据的数量，数据冗余概念。
	// 数据如果冗余，则需要数据同步更新，
	// 原数据更新，冗余数据同步更新。
	//

	// 数据在存储时，要支持多线程，能解决多线程中的脏数据问题。

	// 先分析
	// 设计数据结构
	// list借口 具有存储数据的功能，使用哪个实现类

	// List 接口有序，保留数据的存储顺序
	List<Object> list = new LinkedList<>();
	// map存储数据与次数有关，键值对存储

	Map<Object, Integer> map = new HashMap<>();

	// 监控的数量范围
	final int length = 0;
	// 监控的阈值
	final int count = 0;

	public ValueFilter(int length, int count) {

		this.length = length;
		this.count = count;
	}

	/**
	 * save方法 存储接收的数据，并且统计出相应次数，如果没有超出限制 返回true ,如果超出限制，返回false
	 * 
	 * @param obj 要存储的内容
	 * @return 是否超出阈值e
	 */
	public synchronized boolean save(Object obj) {
		// 判断新数据是否超出阈值
		// 如果超出阈值返回false,并不存储
		// 如果没有超出阈值，存储数据，并且更新出现次数
		// 如果检测的范围超出极限，要移除旧数据，并且更新移除数据得出现次数
		// 1、
		// 在map集合中查询obj对象，出现次数
		Integer obj_count = map.get(obj);
		// 2、如果map中没有存储过这个obj，查询后会返回null
		// 判断obj出现次数的是null,并且，出现的次数没有超出阈值
		if (obj_count == null || obj_count < count) {
			// list.size 获取 存储的数据量
			if (list.size() >= length) {
				// 移除第一个数据
				Object remove_obj = list.remove(0);
				// 将hashmap中存储数据的个数减一
				Integer remove_count = map.get(remove_obj);
				// 如果移除的数据只出现一次
				if (remove_count == 1) {
					// 彻底移除这条记录
					map.remove(remove_obj);

				} else {
					// 重新存储remove_obj键的数据，覆盖旧的value
					// 新的value 是 旧的value-1
					map.put(remove_obj, remove_count - 1);
				}
			}
			// 将新数据存储到list集合
			list.add(obj);
			// 更新map中的数据信息
			// 如果是新数据要存储新的键值，并且数量为“1”
			// 如果是旧数据要存储数量“+1”
			if (obj_count == 0) {
				map.put(obj, 1);
			} else {
				map.put(obj, obj_count + 1);
			}

			return true;

		} else {
			return false;
		}

	}

}
